using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using ProjectEuler.Core.Helpers;

namespace ProjectEuler.Core
{
    public class Problem49 : IProjectEulerProblem
    {
        protected IEnumerable<List<int>> FourDigitIncreasingPrimeSequence()
        {
            var list = new List<List<int>>();
            var fourDigitPrimes = Enumerable.Range(1000, 10000).Where(i => MathHelper.IsPrime(i));
            foreach (var fourDigitPrime in fourDigitPrimes)
            {
                var primePermutations = GetAllPrimePermutationsOf(fourDigitPrime);

                if (primePermutations.Count() < 3) continue;
                
                var primeSequence3330 = GetPrimeSequence3330(primePermutations);
                
                if (!primeSequence3330.Any()) continue;
                
                if (!list.Any(l => l.SequenceEqual(primeSequence3330)))
                {
                    list.Add(primeSequence3330);
                }
            }
            return list;
        }

        private IEnumerable<int> GetAllPrimePermutationsOf(int i)
        {
            var perm = new StringPerm(i.ToString().Select(s => s.ToString()));
            return perm.GetAllPermuations()
                .Where(p => MathHelper.IsPrime(long.Parse(p)))
                .Select(p => int.Parse(p));
        }

        private List<int> GetPrimeSequence3330(IEnumerable<int> primePermutations)
        {
            var orderedPermutations = primePermutations.OrderBy(p => p);
            foreach (var primePermutation in orderedPermutations)
            {
                var other1 = primePermutation + 3330;
                var other2 = primePermutation + 3330 + 3330;
                if(primePermutations.Contains(other1) && primePermutations.Contains(other2))
                {
                    return new List<int> {primePermutation, other1, other2};
                }
            }
            return new List<int>();
        }

        public int Number
        {
            get { return 49; }
        }

        public string Description
        {
            get { return "What 12-digit number do you form by concatenating the three terms?"; }
        }

        public string Answer
        {
            get
            {
                return string.Join("",
                      FourDigitIncreasingPrimeSequence()
                      .Where(l => !l.Contains(1487))
                      .Single()
                      .Select(i => i.ToString()));
            }
        }
    }

    [TestFixture]
    public class Problem49Tests : Problem49
    {
        [Test]
        public void The_given_sequence_should_be_found()
        {
            var sequences = FourDigitIncreasingPrimeSequence().ToList();
            Assert.IsTrue(sequences.Any(s => s.Contains(1487)));
            Assert.AreEqual(2, sequences.Count);
        }
    }
}